package com.shareyi.simpleserver.core;

import java.io.*;
import java.net.HttpURLConnection;

/**
 * This holds the response data for the http response.
 *@author David zhang
 *@since Tue 22 May 2011
 *@version 1.0
 */

public class HttpResponse extends Response {

    private int statusCode = HttpURLConnection.HTTP_OK;
   

    private String mimeType = "text/html";

    private String charset ="utf-8";
    	
    private HttpHeaders responseHeaders;

    private InternetOutputStream stream;

    private ResponseDataList dataStreamList;

    private HttpRequest request;

    private boolean keepConnectionOpen;

    private String errorMsg;

    /**
     * have called the doResponse method ,if have called it will return immediately
     */
    private boolean responsed=false;
    
    
    public HttpResponse( HttpRequest request, OutputStream aStream ) {
        this.stream = new InternetOutputStream( aStream );
        this.request = request;
        this.responseHeaders = new HttpHeaders();
        this.dataStreamList = new ResponseDataList();
        this.keepConnectionOpen = request.isKeepAlive();
    }

    
    public boolean isKeepAlive() {
        return ( keepConnectionOpen && request.isKeepAlive() );
    }

    public void addHeader(String key, String value) {
        responseHeaders.put( key, value );
    }

    public PrintWriter getPrintWriter() {
        return dataStreamList.addPrintWriter();
    }

    public void addResponse(InputStream stream,long length)
    {
    	dataStreamList.addResponse(stream, length);
    }
    
    public void setMimeType( String aMimeType ) {
        mimeType = aMimeType;
    }

    public void setCharset( String charset ) {
    	this.charset = charset;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }
    
    public int getStatusCode() {
        return statusCode;
    }
    
    
    public void setErrorMsg(String errMsg)
    {
    	this.errorMsg=errMsg;
    }
    
    
    
    public void sendError( int statusCode, String errorMessage ) {
        sendError( statusCode, errorMessage, null );
    }

    public void sendError( int statusCode, String errorMessage, Exception e ) {
        keepConnectionOpen = false;
         StringBuilder body =new StringBuilder();
         body.append("<html>\n<head>\n<title>Error: ").append(statusCode)
         .append ("</title>\n<body>\n<h1>").append(statusCode + " <b>")
         .append (Http.getStatusPhrase( statusCode ))
         .append ("</b></h1>");
               if(errorMsg!=null)
            	   body.append(errorMsg);
               else{
               body.append("<br>\nThe requested URL <b>")
                .append(request.getUrl())
                .append("</b>\n ")
                .append(Http.encodeHtml( errorMessage )+ "\n");
               }
               body.append("<hr>");
               
        if( e != null ) {
            StringWriter writer = new StringWriter();
            writer.write("<pre>");
            e.printStackTrace( new PrintWriter( writer ) );
            writer.write("</pre>");
            body .append(writer.toString());
        }
        body.append("</body>\n</html>");

        this.statusCode = statusCode;
        this.mimeType = "text/html";
        PrintWriter out = getPrintWriter();
        out.write( body.toString());
    }
    
    /**
     * 执行响应
     * @throws IOException 
     */
    public void doResponse() throws IOException
    {
    	//如果已经响应，就返回
    	if(responsed)
    		return;
    	
    	if(statusCode!=HttpURLConnection.HTTP_OK)
    	{
    		if(statusCode==1000||statusCode==2000)
    		{
    			PrintWriter writer=getPrintWriter();
    			writer.println(""+statusCode);
    			sendBody();
    			return ;
    		}else if(statusCode!=302)
    		sendError(statusCode, Http.getStatusPhrase(statusCode));
    		else
    		getPrintWriter().println("Please waitting, Redirecting......");
    	}
    	commitResponse();
    	
    	responsed=true;
    }

    
    public void commitResponse() throws IOException {
        try {
            sendHttpReply( statusCode );
            sendHeaders( mimeType, dataStreamList.getTotalLength() );
            if( !isHeadMethod() ) {
                sendBody();
            }
          
        } catch( IOException e ) {
         //   throw e;
        }
    }
    private void sendBody() throws IOException {
        dataStreamList.sendData( stream);
    }

    private void sendHttpReply( int code ) throws IOException {
        StringBuffer buffer = new StringBuffer( request.getProtocol() );
        buffer.append(" ");
        buffer.append( code );
        buffer.append( " ");
        buffer.append( Http.getStatusPhrase( code ) );
        buffer.append( Http.CRLF );
        stream.write( buffer.toString().getBytes() );
    }

    private void sendHeaders(  String mimeType, long contentLength ) throws IOException {
        responseHeaders.put( "Date", Http.getCurrentTime() );
        responseHeaders.put( "Server", "SimpleServer" );
        //String str = request.isKeepAlive() ? "Keep-Alive" : "close";
        String str = "close";
        responseHeaders.put( request.getConnectionHeader(), str );
        if ( contentLength >= 0) {
            responseHeaders.put( "Content-Length", Long.toString(contentLength) );
        }
        if (mimeType != null) {
        	String contentType=mimeType;
        	if(charset!=null)
        		contentType=mimeType+";charset="+charset;
            responseHeaders.put( "Content-Type", contentType);
        }
        responseHeaders.print( stream );
    }
    
    
    
    
    

    private boolean isHeadMethod() {
        return "HEAD".equalsIgnoreCase( request.getMethod() );
    }

    public OutputStream getOutputStream() {
        return stream;
    }
    
    public void redirect(String newUrl){
    	this.statusCode=HttpURLConnection.HTTP_MOVED_TEMP;
    	addHeader("location", newUrl);
    	try {
			this.doResponse();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }

}
